// --------------------------------
//    本模块内容来自 6g3y
// --------------------------------
declare global {
    interface RoomPosition {
        /**
         * 该位置是否可通行
         */
        walkable(withCreep?: boolean, rampartOwnerUserName?: string): boolean
        /**
         * 获取房间坐标
         */
        getRoomCoordinate(): { x: number; y: number }
        /**
         * 跨房是否相邻
         */
        isCrossRoomNearTo(other: RoomPosition): boolean
        /**
         * 跨房间的两点之间的距离
         */
        crossRoomGetRangeTo(other: RoomPosition): number
        /**
         * 减去另一个坐标
         */
        crossRoomSubPos(other: RoomPosition): { x: number; y: number }
        /**
         * 获取指定方向的 RoomPosition
         */
        getDirectPos(direction: DirectionConstant): RoomPosition
        /**
         * 获取指定位置的 rampart
         */
        coverRampart(includeMine?: boolean): StructureRampart | undefined
        /**
         * 获取 RoomPosition 的哈希值
         */
        hashCode(): number
        /**
         * 获取 RoomPosition 在房间内的哈希值
         */
        hashCodeInRoom(): number
        /**
         * 计算 RoomPosition 在全图的坐标
         */
        toGlobal(): { x: number; y: number }
        /**
         * 返回范围内的 posList，不包括自己
         */
        nearPos(range?: number): RoomPosition[]
    }
}

/**
 * 该位置是否可通行
 * 看不见时，只能判定 terrain
 * (划掉，考虑了)修墙里的隧道不考虑（不会有人真的修墙里面吧？
 */
RoomPosition.prototype.walkable = function (withCreep = false, rampartOwnerUserName?: string) {
    if (Game.rooms[this.roomName]) {
        const structure =
            this.lookFor(LOOK_STRUCTURES).every((struct: any) => {
                return !(
                    struct.structureType !== STRUCTURE_CONTAINER &&
                    struct.structureType !== STRUCTURE_ROAD &&
                    (struct.structureType !== STRUCTURE_RAMPART ||
                        (rampartOwnerUserName ? rampartOwnerUserName != struct.owner.username : !struct.my) ||
                        struct.isPublic)
                )
            }) &&
            !(
                this.lookFor(LOOK_TERRAIN).find((o: any) => o === 'wall') &&
                this.lookFor(LOOK_STRUCTURES).every((struct: any) => struct == STRUCTURE_ROAD)
            ) &&
            this.lookFor(LOOK_CONSTRUCTION_SITES).every(
                (s: any) => !_.contains(OBSTACLE_OBJECT_TYPES, s.structureType) || !s.my,
            )
        if (withCreep) {
            const creep = this.lookFor(LOOK_CREEPS).length === 0
            return structure && creep
        } else {
            return structure
        }
    } else {
        return new Room.Terrain(this.roomName).get(this.x, this.y) != 1 // 1 是 wall
    }
}

const CHAR_0 = '0'.charCodeAt(0)
const MAP_DIRECT = { E: 1, N: -1, W: -1, S: 1 } //东西南北坐标
const MAP_OFFSET = { E: 0, N: -1, W: -1, S: 0 } //东西南北坐标

/**
 * 获取房间坐标
 */
const getRoomCoordinate = function (roomName: string) {
    const tmp = { x: 0, y: 0 }
    let sh = 0
    let pow = 1
    for (let i = roomName.length - 1; i >= 0; i--) {
        const cc = roomName.charCodeAt(i) - CHAR_0
        if (cc >= 0 && cc <= 9) {
            if (sh == 0) {
                tmp.y += cc * pow
            } else {
                tmp.x += cc * pow
            }
            pow *= 10
        } else {
            const c = roomName[i] as keyof typeof MAP_DIRECT
            if (sh == 0) {
                tmp.y *= MAP_DIRECT[c]
                tmp.y += MAP_OFFSET[c]
            } else {
                tmp.x *= MAP_DIRECT[c]
                tmp.x += MAP_OFFSET[c]
            }
            pow = 1
            sh += 1
        }
    }
    return tmp
}

/**
 * 获取房间坐标
 */
RoomPosition.prototype.getRoomCoordinate = function () {
    return getRoomCoordinate(this.roomName)
}

/**
 * 跨房是否相邻
 */
RoomPosition.prototype.isCrossRoomNearTo = function (other: RoomPosition) {
    if (this.roomName == other.roomName) return this.isNearTo(other)
    return this.crossRoomGetRangeTo(other) <= 1
}

/**
 * 跨房间的两点之间的距离
 */
RoomPosition.prototype.crossRoomGetRangeTo = function (other: RoomPosition) {
    if (this.roomName == other.roomName) return this.getRangeTo(other)
    const det = this.crossRoomSubPos(other)
    return Math.max(Math.abs(det.x), Math.abs(det.y))
}

/**
 * 减去另一个坐标
 */
RoomPosition.prototype.crossRoomSubPos = function (other: RoomPosition) {
    const sameRoom = this.roomName == other.roomName
    const change = (e: number) => (sameRoom ? e : e == 49 ? 50 : e == 0 ? -1 : e) // 如果房间不一样默认交换位置
    const a = other.getRoomCoordinate()
    const b = this.getRoomCoordinate()
    const x = b.x - a.x
    const y = b.y - a.y
    const tmp = {
        x: change(this.x) + x * 50 - change(other.x),
        y: change(this.y) + y * 50 - change(other.y),
    }
    return tmp
}

const DIRECTION_MAP = {
    [TOP]: [0, -1],
    [TOP_RIGHT]: [1, -1],
    [RIGHT]: [1, 0],
    [BOTTOM_RIGHT]: [1, 1],
    [BOTTOM]: [0, 1],
    [BOTTOM_LEFT]: [-1, 1],
    [LEFT]: [-1, 0],
    [TOP_LEFT]: [-1, -1],
}

function getRoomNameByXY(x: number, y: number) {
    return `${x >= 0 ? 'E' : 'W'}${x >= 0 ? x : -1 - x}${y >= 0 ? 'S' : 'N'}${y >= 0 ? y : -1 - y}`
}

/**
 * 获得 direction 的方向 的 RoomPosition
 * 1000 次 0.8 cpu
 */
RoomPosition.prototype.getDirectPos = function (direction: DirectionConstant) {
    const x = this.x + DIRECTION_MAP[direction][0]
    const y = this.y + DIRECTION_MAP[direction][1]
    let offsetX = 0
    let offsetY = 0
    if (x < 0) offsetX -= 1
    else if (x > 49) offsetX += 1
    if (y < 0) offsetY -= 1
    else if (y > 49) offsetY += 1
    if (offsetX == 0 && offsetY == 0) return new RoomPosition(x, y, this.roomName)
    else {
        const co = getRoomCoordinate(this.roomName)
        return new RoomPosition((x + 50) % 50, (y + 50) % 50, getRoomNameByXY(co.x + offsetX, co.y + offsetY))
    }
}

/**
 * 获取指定位置的 rampart
 */
RoomPosition.prototype.coverRampart = function (includeMine = false) {
    if (!Game.rooms[this.roomName]) return undefined
    return this.lookFor(LOOK_STRUCTURES).find(
        (e: any) => e.structureType == STRUCTURE_RAMPART && (includeMine || !e.my) && !e.isPublic,
    )
}

/**
 * 获取 RoomPosition 的哈希值
 */
RoomPosition.prototype.hashCode = function () {
    const roomCoordinate = this.getRoomCoordinate()
    return (roomCoordinate.x << 19) + (roomCoordinate.y << 13) + (this.x << 6) + this.y
}

/**
 * 获取 RoomPosition 在房间内的哈希值
 */
RoomPosition.prototype.hashCodeInRoom = function () {
    return (this.x << 6) + this.y
}

/**
 * 计算 RoomPosition 在全图的坐标
 */
RoomPosition.prototype.toGlobal = function () {
    const roomCoordinate = this.getRoomCoordinate()
    return {
        x: roomCoordinate.x * 50 + this.x,
        y: roomCoordinate.y * 50 + this.y,
    }
}

/**
 * 返回范围内的 posList，不包括自己
 */
RoomPosition.prototype.nearPos = function (range = 1) {
    const arr = []
    for (let i = -range; i <= range; i++) {
        for (let j = -range; j <= range; j++) {
            if ((i || j) && this.x + i >= 0 && this.y + j >= 0 && this.x + i <= 49 && this.y + j <= 49)
                arr.push(new RoomPosition(this.x + i, this.y + j, this.roomName))
        }
    }
    return arr
}

export {}
